package com.sx.manage.controller.entry;

import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.net.URLEncoder;
import java.util.Map;

import javax.annotation.Resource;
import javax.servlet.ServletException;
import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;

import com.sx.cache.Session;
import com.sx.common.util.json.JackJsonUtil;
import com.sx.common.vo.BaseVO;
import com.sx.manage.biz.consumer.system.IMSystemConsumerBiz;
import com.sx.manage.biz.login.IMSystemConsumerLoginBiz;
import com.sx.manage.controller.base.MBaseController;
import com.sx.manage.exception.MNotHaveLoginExceptionAjax;
import com.sx.manage.servlet.ViewAndModel;
import com.sx.manage.util.SessionManager;
import com.sx.model.constants.MSystemConstants;
import com.sx.model.constants.type.consumer.MConsumersNatures;
import com.sx.model.manage.mybatis.vo.consumer.MSystemConsumerInfoVO;
import com.sx.model.manage.mybatis.vo.consumer.login.MConsumerLoginVO;
import com.sx.model.manage.mybatis.vo.result.ResultBooleanVO;
import com.sx.model.manage.mybatis.vo.result.ResultObjectVO;
import com.sx.model.manage.mybatis.vo.result.ResultPassObjectVO;

/**
 * 用户登录 控制器
 * 
 * @author zhenzhanlong
 *
 */
@Controller
@RequestMapping("/entry")
@SuppressWarnings({ "unchecked", "rawtypes" })
public class MEntryController extends MBaseController {
	private Logger _log = LoggerFactory.getLogger(this.getClass());
	// 系统用户biz
	@Resource(name = "systemConsumerBizImpl")
	private IMSystemConsumerBiz systemConsumerBizImpl;
	// 登陆biz
	@Resource(name = "mSystemConsumerLoginBizImpl")
	private IMSystemConsumerLoginBiz mSystemConsumerLoginBizImpl;

	/**
	 * 登录
	 * 
	 * @param modelStr
	 * @param returnUrl
	 * @param request
	 * @param response
	 * @param model
	 * @return
	 * @throws Exception
	 */
	@RequestMapping(value = "/signIn", produces = { "application/json;charset=UTF-8" })
	@ResponseBody
	public ViewAndModel login(MSystemConsumerInfoVO consumerVO, String remember, HttpServletRequest request, HttpServletResponse response) {
		ViewAndModel model = null;
		_log.info("路径：" + request.getContextPath());
		Session session = SessionManager.createtoken(request, response, cache);
		// 系统用户登录
		ResultObjectVO<MConsumerLoginVO> result = mSystemConsumerLoginBizImpl.systemConsumerLoginValidate(consumerVO);
		if (result.isSuccess()) {
			MConsumerLoginVO consumerLoginVO = result.getObjVo();
			String consumerTokenKey = MSystemConstants.MODULE_USER_CENTER + consumerLoginVO.getConsumer_id();
			// 加入用户登录ip
			consumerLoginVO.setIp_address(getIp(request));
			_log.debug("用户获取的ip:" + consumerLoginVO.getIp_address());
			// 查询当前的用户是否登陆过
			String oldtoken = session.gettokenbyuserid(consumerTokenKey);
			if (oldtoken != null) {
				_log.info("用户已经登陆:userid={},token={}" + consumerTokenKey, oldtoken);
				// 删除旧的session
				if (session.removeold(oldtoken)) {
					_log.info("删除旧的用户session成功={}", oldtoken);
				} else {
					_log.info("删除旧的用户session失败={}", oldtoken);
				}
			}
			// 更新登陆记录
			if (session.setuserbytoken(consumerTokenKey, null)) {
				_log.info("更新用户登陆记录成功={}", consumerTokenKey);
			} else {
				_log.info("更新用户登陆记录失败={}", consumerTokenKey);
			}
			try {
				_log.debug("用户信息放入缓存");
				session.put("user_id", consumerTokenKey);
				String userJson = JackJsonUtil.objToJson(consumerLoginVO);
				session.put("user", userJson);
			} catch (Exception e) {
				_log.error("用户新入缓存", e);
			}
			model = new ViewAndModel("index", request, cache);
			model.addObject("user", consumerLoginVO);
			model.addObject("func_list", this.mSystemConsumerLoginBizImpl.function_cache_query_function_vo(MSystemConstants.CACHE_TYPE_SYSTEM_CONSUMER_FUNCTION, consumerLoginVO.getConsumer_id(), null).getData());
			//setCookie(response,MSystemConstants.TOKEN_MANAGER,session.get_token());
		} else {
			// 跳转登录失败界面
			model = new ViewAndModel("entry/m_entry", request, cache);
			// 失败信息 带到界面上
			model.addObject("error", result.getMsg());
		}
		return model;
	}
	   /**
     * 保存Cookies
     * 
     * @param response
     *            servlet请求
     * @param value
     *            保存值
     * @author jxf
     */
    public  HttpServletResponse setCookie(HttpServletResponse response, String name, String value) {
        // new一个Cookie对象,键值对为参数
        Cookie cookie = new Cookie(name, value);
        // tomcat下多应用共享
        cookie.setPath("/");
        // 如果cookie的值中含有中文时，需要对cookie进行编码，不然会产生乱码
        try {
            URLEncoder.encode(value, "utf-8");
        } catch (UnsupportedEncodingException e) {
           _log.error("设置cookie编码时异常",e);
        }
        cookie.setMaxAge(MSystemConstants.LOGIN_TIME_SET_UP);
        // 将Cookie添加到Response中,使之生效
        response.addCookie(cookie); // addCookie后，如果已经存在相同名字的cookie，则最新的覆盖旧的cookie
        return response;
    }
	/*** 重新登录 ***/
	@RequestMapping(value = "reSign")
	public ViewAndModel reSign() {
		_log.info("跳转到重新登录界面");
		// 跳转到登录页
		ViewAndModel model = new ViewAndModel("entry/m_entry", request, cache);
		try {
			// 清空缓存中的用户信息
			clearUser();
		} catch (MNotHaveLoginExceptionAjax e) {
			_log.error("重新登录操作,但是此时用户已经失效：error={}", e);
		}
		return model;
	}

	/*** 重新登录 ***/
	@RequestMapping(value = "notHaveLogin")
	@ResponseBody
	public BaseVO notHaveLogin() {
		_log.info("用户登录超时，请重新登录");
		return BaseVO.createErrorMsg("用户登录超时，请重新登录");
	}

	/**
	 * 用户已经登录提示
	 * 
	 * @return
	 * @throws ServletException
	 * @throws IOException
	 */
	@RequestMapping(value = "haveSign")
	public ViewAndModel haveSign() {
		_log.info("跳转到重新登录界面");
		// 跳转到首页登录页
		ViewAndModel model = new ViewAndModel("entry/m_entry", request, cache);
		model.addObject("error", "当前用户已在其他设备登陆");
		return model;
	}

	/**** 退出 ***/
	@RequestMapping(value = "signOut")
	public ViewAndModel signOut() {
		// 跳转到 首页（未实现）
		ViewAndModel model = new ViewAndModel("entry/m_entry", request, cache);
		_log.debug("用户退出操作：");
		try {
			// 清空缓存中的用户信息
			clearUser();
		} catch (MNotHaveLoginExceptionAjax e) {
			_log.error("用户退出操作,但是此时用户已经失效：error={}", e);
		}
		return model;
	}

	/** 重新写 清理缓存 **/
	private ResultBooleanVO clearUser() {
		try {
			// 清空缓存中的用户信息
			MConsumerLoginVO consumerLoginVO = null;
			Session session = SessionManager.instance(request, response, cache);
			if (session.istokenexists()) {
				String userJson = session.get("user");
				if (StringUtils.isNotBlank(userJson)) {
					consumerLoginVO = JackJsonUtil.jsonToJavaBean(userJson, MConsumerLoginVO.class);
				}
			}
			// 清空缓存中的用户信息
			if (null != consumerLoginVO) {
					String consumerTokenKey = MSystemConstants.MODULE_USER_CENTER + consumerLoginVO.getConsumer_id();
				// 查询当前的用户是否登陆过
				String oldtoken = session.gettokenbyuserid(consumerTokenKey);
				if (oldtoken != null && session.removeold(oldtoken)) {
					_log.info("用户退出系统:userid:{},token:{}", consumerLoginVO.getConsumer_id().toString(), oldtoken);
					// 删除旧的session
					_log.info("删除旧的用户session成功:{}", oldtoken);
				} else if (oldtoken != null) {
					_log.info("删除旧的用户session失败:{}", oldtoken);
				}
				mSystemConsumerLoginBizImpl.delete_authority(MConsumersNatures.USER_CENTER, consumerLoginVO.getConsumer_id(), null);
			} else {
				_log.debug("用户信息在内存中，已经超时");
			}
		} catch (Exception e) {
			_log.error("清空用户缓存时出错：", e);
			return new ResultBooleanVO(false, null, "清空用户缓存时出错");
		}
		return new ResultBooleanVO();
	}

	/*** 数据库连接中断 ***/
	@RequestMapping(value = "communications")
	public ViewAndModel communications() {
		return this.error("数据库连接出现中断问题");
	}

	/*** 数据库连接中断 ***/
	/**/@RequestMapping(value = "unknownException")
	@ResponseBody
	public ViewAndModel unknownException(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) {
		_log.info("程序出现未知错误，跳转到重新登录界面");
		// 跳转到登录页
		ViewAndModel model = new ViewAndModel("entry/m_entry", request, cache);
		model.addObject("error", "程序出现未知错误，跳转到重新登录界面");
		return model;
	}

	/*** 界面跳转错误 ***/
	@RequestMapping(value = "modelException")
	public ViewAndModel modelException() {
		ViewAndModel model = new ViewAndModel("error/no_authority", request, cache);
		model.addObject("error", "程序出现未知错误，跳转到重新登录界面");
		return model;
	}

	/*** ajax 错误 ***/
	@RequestMapping(value = "ajaxException")
	@ResponseBody
	public BaseVO ajaxException() {
		return BaseVO.createErrorMsgBykey("sj.m.function.button.user.not.configure");
	}

	/*** ajax 错误 (抛出此异常是为了进行实物回滚) ***/
	@RequestMapping(value = "ajaxRollbackException")
	@ResponseBody
	public BaseVO ajaxRollbackException(String error) {
		return BaseVO.createErrorMsg(error);
	}

	/*** 界面跳转错误 ***/
	@RequestMapping(value = "modelNotCaughtException")
	public ViewAndModel modelNotCaughtException() {
		ViewAndModel model = new ViewAndModel("index", request, cache);
		model.addObject("not_caught_exception", "程序出现错误，操作失败");
		return model;
	}

	/*** ajax 未捕获异常 错误 ***/
	@RequestMapping(value = "ajaxNotCaughtException")
	@ResponseBody
	public BaseVO ajaxNotCaughtException() {
		return BaseVO.createErrorMsgBykey("sj.m.not.caught.exception.ajax.exception");
	}

	/**
	 * 公共错误登录跳转
	 * 
	 * @param error
	 * @return
	 */
	private ViewAndModel error(String error) {
		ViewAndModel errorView = new ViewAndModel("entry/m_entry", request, cache);
		errorView.addObject("error", error);
		return errorView;
	}

	/** 500错误响应 **/
	@RequestMapping(value = "internalServerError")
	private ViewAndModel internalServerError(String error) {
		ViewAndModel errorView = new ViewAndModel("error/500", request, cache);
		errorView.addObject("error", error);
		return errorView;
	}

	/** 400错误响应 **/
	@RequestMapping(value = "notFind")
	private ViewAndModel notFind(String error) {
		ViewAndModel errorView = new ViewAndModel("error/404", request, cache);
		errorView.addObject("error", error);
		return errorView;
	}

	/**
	 * 忘记密码- 获取验证码
	 * 
	 * @return
	 */
	@RequestMapping(value = "getPin_code_")
	@ResponseBody
	public ResultBooleanVO getPin_code_(HttpServletRequest request, HttpServletResponse response, String mobile) {
		if (null == mobile) {
			return new ResultBooleanVO(false, null, "请填写手机号");
		}
		ResultBooleanVO re = systemConsumerBizImpl.queryPinCode(mobile, null);
		if (!re.isSuccess()) {
			return new ResultBooleanVO(false, null, "验证码发送失败");
		}
		return new ResultBooleanVO(true, null, "验证码发送成功");

	}

	/**
	 * 忘记密码- 下一步
	 * 
	 * @param request
	 * @param response
	 * @return
	 * @throws ServletException
	 * @throws IOException
	 */
	@RequestMapping(value = "next_step")
	@ResponseBody
	public ResultPassObjectVO next_step(String mobile, String pinCode) {
		_log.debug("忘记密码下一步");
		if (StringUtils.isBlank(mobile) || StringUtils.isBlank(pinCode)) {
			return new ResultPassObjectVO(false, null, "手机号或验证码为空");
		}
		return systemConsumerBizImpl.nextStep(mobile, pinCode);
	}

	/**
	 * 忘记密码- 重新设置-密码
	 * 
	 * @param request
	 * @param response
	 * @return
	 * @throws ServletException
	 * @throws IOException
	 */
	@RequestMapping(value = "reset_password")
	@ResponseBody
	public ResultBooleanVO reset_password(Long id, String newPassword, String confirmNewPassword) {
		_log.debug("系统用户重置密码 reset_password  ，id=" + id + ",newPassword=" + newPassword + ",confirmNewPassword=" + confirmNewPassword);
		if (null == id || StringUtils.isBlank(newPassword) || StringUtils.isBlank(confirmNewPassword)) {
			return new ResultBooleanVO("m.parameter.is.null");
		}
		return systemConsumerBizImpl.resetPassword(id, newPassword, confirmNewPassword);
	}

	/** 修改用户名，密码 */
	@RequestMapping(value = "updateConsumerPassword")
	@ResponseBody
	public ResultBooleanVO updateConsumerPassword(HttpServletRequest request, HttpServletResponse response) throws IOException {
		String requestMessage = extractParamFromRequest(request);
		Map<String, String> map = JackJsonUtil.jsonToMap(requestMessage, String.class, String.class);
		_log.info("修改用户名密码consumer_Id={},new_pass={}", map.get("consumer_Id"), map.get("new_password"));
		MConsumerLoginVO loginVO = loginConsumer();
		loginVO.setPassword(map.get("password"));
		return systemConsumerBizImpl.updatePassword(Long.valueOf(map.get("consumer_Id")), map.get("new_password"), loginVO);
	}

	/** 获取ip **/
	public String getIp(HttpServletRequest request) {
		String ip = request.getHeader("X-Forwarded-For");
		_log.debug("getIp ip1：" + ip);
		if (StringUtils.isNotEmpty(ip) && !"unKnown".equalsIgnoreCase(ip)) {
			// 多次反向代理后会有多个ip值，第一个ip才是真实ip
			int index = ip.indexOf(',');
			if (index != -1) {
				return ip.substring(0, index);
			} else {
				return ip;
			}
		}
		ip = request.getHeader("X-Real-IP");
		_log.debug("getIp ip2：" + ip);
		if (StringUtils.isNotEmpty(ip) && !"unKnown".equalsIgnoreCase(ip)) {
			return ip;
		}
		ip = request.getRemoteAddr();
		_log.debug("getIp ip3：" + ip);
		return ip;
	}

}
